package com.hhf.rpc.core.protocol;

import com.hhf.rpc.core.constant.ProtocolConstant;
import com.hhf.rpc.core.enums.ProtocolMessageSerializerEnum;
import com.hhf.rpc.core.enums.ProtocolMessageTypeEnum;
import com.hhf.rpc.core.model.RpcRequest;
import com.hhf.rpc.core.model.RpcResponse;
import com.hhf.rpc.core.serializer.Serializer;
import com.hhf.rpc.core.serializer.SerializerFactory;
import io.vertx.core.buffer.Buffer;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;

/**
 * @Author hhf
 * @Date 2024/10/19
 * @Description 解码器
 */
@Slf4j
public class ProtocolMessageDecoder {

    public static ProtocolMessage<?> decode(Buffer buffer) throws IOException {

        //1.从bufferd的指定位置读取数据(获取的数据应与请求构造的数据位置一致)
        //          buffer.appendByte(magic);
        //          buffer.appendByte(version);
        //          buffer.appendByte(serializer);
        //          buffer.appendByte(status);
        //          buffer.appendByte(type);
        //          buffer.appendLong(requestId);
        //          buffer.appendInt(bodyLength);
        //          buffer.appendBytes(bodyBytes);
        //

        byte magic = buffer.getByte(0);
        //校验魔数,安全性
        if (magic != ProtocolConstant.PROTOCOL_MAGIC) {
            throw new RuntimeException("消息 magic 非法");
        }

        byte version = buffer.getByte(1);
        byte serializer = buffer.getByte(2);
        byte status = buffer.getByte(3);
        byte type = buffer.getByte(4);
        Long requestId = buffer.getLong(5);
        int bodyLength = buffer.getInt(13);
        //解决粘包问题,只读取指定长度
        byte[] bodyBytes = buffer.getBytes(17, 17 + bodyLength);
        //2.构造请求/响应
        ProtocolMessage.Header header = new ProtocolMessage.Header();
        header.setType(type);
        header.setMagic(magic);
        header.setStatus(status);
        header.setSerializer(serializer);
        header.setVersion(version);
        header.setRequestId(requestId);
        //3.获取序列化器,对消息体进行反序列化
        ProtocolMessageSerializerEnum serializerEnum = ProtocolMessageSerializerEnum.getSerializerByKey(serializer);
        if (serializerEnum == null){
            log.error("序列化器:{}不存在",serializerEnum.toString());
        }
        ProtocolMessageTypeEnum typeEnum = ProtocolMessageTypeEnum.getEnumByKey(type);
        if (typeEnum == null){
            log.error("序列化消息的类型:{}不存在",typeEnum.toString());
        }

        Serializer serializerInstance = SerializerFactory.getSerializerInstance(serializerEnum.getValue());
        //3.返回
        switch (typeEnum){
            case REQUEST -> {
                RpcRequest rpcRequest = serializerInstance.deSerialize(bodyBytes, RpcRequest.class);
                return new ProtocolMessage<>(rpcRequest,header);
            }
            case RESPONSE -> {
                RpcResponse rpcResponse = serializerInstance.deSerialize(bodyBytes, RpcResponse.class);
                return new ProtocolMessage<>(rpcResponse,header);
            }
            default -> {
                log.error("暂不支持该类型的消息");
                throw new RuntimeException("暂不支持该类型的消息");
            }
        }



    }
}
